package com.basic.business.goodsIndicators.service.impl;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.read.listener.ReadListener;
import cn.idev.excel.util.ListUtils;
import com.basic.business.declineWarnBoard.vo.DeclineWarnBoardReqVo;
import com.basic.business.declineWarnBoard.vo.DeclineWarnBoardRespVo;
import com.basic.business.goodsIndicators.domain.TGoodsIndicators;
import com.basic.business.goodsIndicators.dto.TGoodsIndicatorsDto;
import com.basic.business.goodsIndicators.dto.TGoodsUpNewDateDto;
import com.basic.business.goodsIndicators.mapper.TGoodsIndicatorsMapper;
import com.basic.business.goodsIndicators.service.ITGoodsIndicatorsService;
import com.basic.business.goodsIndicators.vo.CollectData;
import com.basic.business.goodsIndicators.vo.TGoodsIndicatorsVo;
import com.basic.business.goodsLabel.domain.TGoodsLabel;
import com.basic.business.goodsLabel.mapper.TGoodsLabelMapper;
import com.basic.business.indicatorsFile.service.ITIndicatorsFileService;
import com.basic.business.kanban.vo.*;
import com.basic.business.unIndicators.mapper.TUnboundedIndicatorsMapper;
import com.basic.business.wholeIndicators.mapper.TWholeStationIndicatorsMapper;
import com.basic.common.annotation.DataScope;
import com.basic.common.core.service.impl.BaseServiceImpl;
import com.basic.common.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品指标数据Service业务层处理
 *
 * @author zhaoxy_jn@163.com
 */
@Service
public class TGoodsIndicatorsServiceImpl extends BaseServiceImpl<TGoodsIndicatorsMapper,TGoodsIndicators> implements ITGoodsIndicatorsService {
    @Resource
    private TGoodsIndicatorsMapper tGoodsIndicatorsMapper;

    @Resource
    private ITIndicatorsFileService itIndicatorsFileService;

    @Resource
    private TWholeStationIndicatorsMapper tWholeStationIndicatorsMapper;

    @Resource
    private TUnboundedIndicatorsMapper tUnboundedIndicatorsMapper;

    @Resource
    private TGoodsLabelMapper tGoodsLabelMapper;

    @Override
    public int deleteByFileId(String fileId) {
        return tGoodsIndicatorsMapper.deleteByFileId(fileId);
    }

    @Override
    @DataScope(deptAlias = "z")
    public List<TGoodsIndicatorsVo> getListVo(TGoodsIndicators tGoodsIndicators) {
        return tGoodsIndicatorsMapper.getListVo(tGoodsIndicators);
    }

    @Override
    @DataScope(deptAlias = "z")
    public List<TGoodsIndicatorsVo> getSummaryListVo(TGoodsIndicators tGoodsIndicators) {
        return tGoodsIndicatorsMapper.getSummaryListVo(tGoodsIndicators);
    }

    @Override
    public int saveBatch(List<TGoodsIndicators> list) {
        return tGoodsIndicatorsMapper.saveBatch(list);
    }

    @Override
    public int deleteOldData(String storeId, Date statDate, List<String> goodsIdList) {
        return tGoodsIndicatorsMapper.deleteOldData(storeId,statDate,goodsIdList);
    }

    @Override
    public List<TGoodsIndicators> getByGoodsId(String goodsId) {
        return tGoodsIndicatorsMapper.getByGoodsId(goodsId);
    }

    @Override
    public List<TGoodsIndicators> getByGoodsIdList(List<String> goodsIdList) {
        return tGoodsIndicatorsMapper.getByGoodsIdList(goodsIdList);
    }

    @Override
    public List<TGoodsUpNewDateDto> exportNoUpNewDate(Long deptId) {
        return tGoodsIndicatorsMapper.exportNoUpNewDate(deptId);
    }

    @Override
    public List<TGoodsIndicators> getListByIds(String[] ids) {
        return tGoodsIndicatorsMapper.getListByIds(ids);
    }

    @DataScope(deptAlias = "g")
    @Override
    public List<Map<String, Object>> getProductEchelon(ProductEchelonVo productEchelonVo) {
        return tGoodsIndicatorsMapper.getProductEchelon(productEchelonVo);
    }

    @Override
    @DataScope(deptAlias = "z")
    public CollectData getCollectData(TGoodsIndicators tGoodsIndicators) {
        return tGoodsIndicatorsMapper.getCollectData(tGoodsIndicators);
    }

    @DataScope(deptAlias = "g")
    @Override
    public List<Map<String, Object>> getProductMonthEchelon(ProductMonthEchelonVo productMonthEchelonVo) {
        return tGoodsIndicatorsMapper.getProductMonthEchelon(productMonthEchelonVo);
    }

    @Override
    @DataScope(deptAlias = "g")
    public List<LinkManageRespVo> getLinkData(LinkManagePageReqVo vo) {
        return tGoodsIndicatorsMapper.getLinkData(vo);
    }

    @Transactional
    @Override
    public int deleteByIdsNew(String[] ids) {

        //获取删除id记录的商品id和统计日期
        List<TGoodsIndicators> goodsIdList = tGoodsIndicatorsMapper.getListByIds(ids);

        //同步删除
        tWholeStationIndicatorsMapper.deleteByGoodsId(goodsIdList);
        tUnboundedIndicatorsMapper.deleteByGoodsId(goodsIdList);

        return tGoodsIndicatorsMapper.deleteByIdsNew(ids);
    }

    @Override
    public int updateLabelByGoodsId(String goodsLabel, String goodsId) {
        return tGoodsIndicatorsMapper.updateLabelByGoodsId(goodsLabel,goodsId);
    }

    @Transactional
    @Override
    public void uploadIndicatorsData(MultipartFile file, Date goodsSelectDate, String goodsStoreId, String fileHash) {

        //文件上传
        String fileId = itIndicatorsFileService.uploadIndicatorsFile(file, goodsSelectDate, goodsStoreId, fileHash, 2);

        try {
            EasyExcel.read(file.getInputStream(), TGoodsIndicatorsDto.class, new ReadListener<TGoodsIndicatorsDto>() {
                /**
                 * 单次缓存的数据量
                 */
                public static final int BATCH_COUNT = 500;

                /**
                 *临时存储
                 */
                private List<TGoodsIndicators> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);


                /**
                 * 解析调用
                 * @param data
                 * @param analysisContext
                 */
                @Override
                public void invoke(TGoodsIndicatorsDto data, AnalysisContext analysisContext) {
                    TGoodsIndicators tGoodsIndicators = new TGoodsIndicators();
                    tGoodsIndicators.setId(null);
                    tGoodsIndicators.setStoreId(goodsStoreId);
                    tGoodsIndicators.setFileId(fileId);
                    tGoodsIndicators.setStatDate(data.getStatDate());
                    tGoodsIndicators.setGoodsId(data.getGoodsId());
                    tGoodsIndicators.setGoodsName(data.getGoodsName());
                    tGoodsIndicators.setMainGoodsId(data.getMainGoodsId());
                    tGoodsIndicators.setGoodsType(data.getGoodsType());
                    tGoodsIndicators.setGoodsNo(data.getGoodsNo());
                    tGoodsIndicators.setGoodsStatus(data.getGoodsStatus());
                    tGoodsIndicators.setGoodsLabel(data.getGoodsLabel());
                    tGoodsIndicators.setGoodsVisitorNumber(convertField(data.getGoodsVisitorNumber())?0:Integer.parseInt(data.getGoodsVisitorNumber().replace(",","")));
                    tGoodsIndicators.setGoodsPageViewNumber(convertField(data.getGoodsPageViewNumber())?0:Integer.parseInt(data.getGoodsPageViewNumber().replace(",","")));
                    tGoodsIndicators.setAverageStopDuration(convertField(data.getAverageStopDuration())?0:Double.parseDouble(data.getAverageStopDuration().replace(",","")));
                    tGoodsIndicators.setGoodsDetailJumpRatio(data.getGoodsDetailJumpRatio().replace(",",""));
                    tGoodsIndicators.setGoodsCollectPeopleNumber(convertField(data.getGoodsCollectPeopleNumber())?0:Integer.parseInt(data.getGoodsCollectPeopleNumber().replace(",","")));
                    tGoodsIndicators.setGoodsAddPurchaseNumber(convertField(data.getGoodsAddPurchaseNumber())?0:Integer.parseInt(data.getGoodsAddPurchaseNumber().replace(",","")));
                    tGoodsIndicators.setGoodsAddPurchasePeopleNumber(convertField(data.getGoodsAddPurchasePeopleNumber())?0:Integer.parseInt(data.getGoodsAddPurchasePeopleNumber().replace(",","")));
                    tGoodsIndicators.setOrderBuyerNumber(convertField(data.getOrderBuyerNumber())?0:Integer.parseInt(data.getOrderBuyerNumber().replace(",","")));
                    tGoodsIndicators.setOrderNumber(convertField(data.getOrderNumber())?0:Integer.parseInt(data.getOrderNumber().replace(",","")));
                    tGoodsIndicators.setOrderAmount(convertField(data.getOrderAmount())?new BigDecimal(0):new BigDecimal(data.getOrderAmount().replace(",","")));
                    tGoodsIndicators.setOrderConversionRatio(convertField(data.getOrderConversionRatio())?null:data.getOrderConversionRatio().replace(",",""));
                    tGoodsIndicators.setPayBuyerNumber(convertField(data.getPayBuyerNumber())?0:Integer.parseInt(data.getPayBuyerNumber().replace(",","")));
                    tGoodsIndicators.setPayNumber(convertField(data.getPayNumber())?0:Integer.parseInt(data.getPayNumber().replace(",","")));
                    tGoodsIndicators.setPayAmount(convertField(data.getPayAmount())?new BigDecimal(0):new BigDecimal(data.getPayAmount().replace(",","")));
                    tGoodsIndicators.setGoodsPayConversionRatio(convertField(data.getGoodsPayConversionRatio())?null:data.getGoodsPayConversionRatio().replace(",",""));
                    tGoodsIndicators.setPayNewBuyerNumber(convertField(data.getPayNewBuyerNumber())?0:Integer.parseInt(data.getPayNewBuyerNumber().replace(",","")));
                    tGoodsIndicators.setPayOldBuyerNumber(convertField(data.getPayOldBuyerNumber())?0:Integer.parseInt(data.getPayOldBuyerNumber().replace(",","")));
                    tGoodsIndicators.setOldBuyerPayAmount(convertField(data.getOldBuyerPayAmount())?new BigDecimal(0):new BigDecimal(data.getOldBuyerPayAmount().replace(",","")));
                    tGoodsIndicators.setJhsPayAmount(convertField(data.getJhsPayAmount())?null:new BigDecimal(data.getJhsPayAmount().replace(",","")));
                    tGoodsIndicators.setVisitorAverageValue(convertField(data.getVisitorAverageValue())?null:new BigDecimal(data.getVisitorAverageValue().replace(",","")));
                    tGoodsIndicators.setSuccessRefundAmount(convertField(data.getSuccessRefundAmount())?new BigDecimal(0):new BigDecimal(data.getSuccessRefundAmount().replace(",","")));
                    tGoodsIndicators.setCompetitiveScore(data.getCompetitiveScore().replace(",",""));
                    tGoodsIndicators.setYearPayAmount(convertField(data.getYearPayAmount())?new BigDecimal(0):new BigDecimal(data.getYearPayAmount().replace(",","")));
                    tGoodsIndicators.setMonthPayAmount(convertField(data.getMonthPayAmount())?new BigDecimal(0):new BigDecimal(data.getMonthPayAmount().replace(",","")));
                    tGoodsIndicators.setMonthPayNumber(convertField(data.getMonthPayNumber())?new Integer(0):Integer.valueOf(data.getMonthPayNumber().replace(",","")));
                    tGoodsIndicators.setSearchPayRatio(data.getSearchPayRatio().replace(",",""));
                    tGoodsIndicators.setSearchVisitorNumber(convertField(data.getSearchVisitorNumber())?0:Integer.parseInt(data.getSearchVisitorNumber().replace(",","")));
                    tGoodsIndicators.setSearchBuyerNumber(convertField(data.getSearchBuyerNumber())?null:Integer.valueOf(data.getSearchBuyerNumber().replace(",","")));
                    tGoodsIndicators.setStructuredDetailConversionRatio(data.getStructuredDetailConversionRatio().replace(",",""));
                    tGoodsIndicators.setStructuredDetailDealProportion(data.getStructuredDetailDealProportion().replace(",",""));

                    tGoodsIndicators.setCreateTime(new Date());
                    tGoodsIndicators.setCreateBy(SecurityUtils.getUsername());
                    tGoodsIndicators.setUserId(SecurityUtils.getUserId());
                    tGoodsIndicators.setDeptId(SecurityUtils.getDeptId());

                    cachedDataList.add(tGoodsIndicators);

                    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
                    if (cachedDataList.size() >= BATCH_COUNT) {
                        //汇总需要清除的旧数据
                        List<String> deleteGoodsIdList = cachedDataList.stream().map(TGoodsIndicators::getGoodsId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(goodsStoreId,cachedDataList.get(0).getStatDate(),deleteGoodsIdList);
                        //存储新数据
                        saveBatch(cachedDataList);
                        // 存储完成清理 list
                        cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                    }

                }

                /**
                 * 所有数据解析完成调用
                 *
                 * @param context
                 */
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (!cachedDataList.isEmpty()){
                        //汇总需要清除的旧数据
                        List<String> deleteGoodsIdList = cachedDataList.stream().map(TGoodsIndicators::getGoodsId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(goodsStoreId,cachedDataList.get(0).getStatDate(),deleteGoodsIdList);
                        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
                        saveBatch(cachedDataList);
                    }
                }
            }).sheet().headRowNumber(5).doRead();
        } catch (Exception e) {
            throw new RuntimeException("文件内容解析错误,文件上传失败!",e);
        }
    }

    /**
     * 判断字段
     * @param input
     * @return
     */
    public static boolean convertField(String input) {
        return input == null || input.isEmpty() || "-".equals(input);
    }

    @Override
    public void scheduledUpdateGoodsLabel() {
        //获取昨日上传的商品标签数据
        List<TGoodsLabel> list = tGoodsLabelMapper.getYesterDayList();

        if (list != null && !list.isEmpty()){

            tGoodsIndicatorsMapper.batchUpdateGoodsLabels(list);
        }

    }


    @Override
    @DataScope(deptAlias = "g")
    public List<UnsalableRespVo> getUnsalableData(UnsalablePageReqVo unsalablePageReqVo) {
        return tGoodsIndicatorsMapper.getUnsalableData(unsalablePageReqVo);
    }

    @DataScope(deptAlias = "g")
    @Override
    public List<DeclineWarnBoardRespVo> getDeclineWarnBoardData(DeclineWarnBoardReqVo declineWarnBoardReqVo) {
        return tGoodsIndicatorsMapper.getDeclineWarnBoardData(declineWarnBoardReqVo);
    }
}
